Skip to content

feat(rich-markdown-editor): round-trip gate, VSCode/style paste, highlight, block reorder#5539

Merged
waleedlatif1 merged 4 commits into
stagingfrom
feat/md-editor-parity
Jul 9, 2026
Merged

feat(rich-markdown-editor): round-trip gate, VSCode/style paste, highlight, block reorder#5539
waleedlatif1 merged 4 commits into
stagingfrom
feat/md-editor-parity

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

A correctness + capability pass on the rich-markdown (.md) editor. Everything here is empirically verified in a real-browser ProseMirror harness and covered by CI tests.

Correctness — read-only gate (round-trip-safety.ts)

Two silent-corruption cases the idempotency probe can't see:

  • Uppercase HTML entities (&/</>) slipped past a case-insensitive safe-list but aren't round-tripped by the serializer → now case-sensitive, opens read-only.
  • Orphan reference definitions ([x]: url with no [x] use) were dropped entirely on first edit → detected and opened read-only; used definitions still inline losslessly.

Paste (markdown-paste.ts)

  • VSCode code paste — reads the vscode-editor-data payload and pastes a real fenced code block with the source language, instead of flattening the colored-span HTML into plain paragraphs.
  • <style>/<script> striptransformPastedHTML removes them so pasting from Google Sheets/Word doesn't leak raw CSS into the doc.

Capabilities

  • Highlight ==mark== — a <mark> mark serialized to/from ==text== (custom marked tokenizer so nested marks like ==**bold**== survive; comparison operators x == y stay literal). Input rule, paste rule, ⌘⇧H, bubble-menu button, themed styling.
  • Keyboard block reordering⌘⇧↑/⌘⇧↓ moves the current top-level block, carrying the caret.

Validation

  • Mark stacking matrix — bold/italic/strike/code/highlight combined and nested across paragraphs, headings, lists, blockquotes, links, and (pipe-escaped) table cells — all idempotent, no stacking bugs. Locked in as CI tests.

Deliberately not done

  • Single-tilde ~x~~x~ and ~~x~~ both render <del>x</del> per the GFM spec (one-or-two tildes = strikethrough), so our single→double normalization is lossless, not a meaning change. Left as-is.
  • Hover +/grip drag-handle — the keyboard reorder above is the robust core; the hover UI needs a drag-handle dep + visual iteration, best done with live visual QA. Recommended as a focused follow-up.

Testing

Real-browser harness (60+ cases) + committed Vitest in CI: round-trip idempotency, mark stacking, highlight parse/serialize/nesting/safety, block reorder, entity/ref-def gate. No regressions.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 9, 2026 8:21pm

Request Review

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes affect markdown save safety (editability gate), paste handling, and document mutation on reorder/highlight—well tested but touches user-facing file content paths.

Overview
Expands the workspace rich markdown editor with Obsidian-style ==highlight== (schema mark, bubble menu, ⌘⇧H, markdown round-trip with guards for unrepresentable == in highlighted text) and ⌘⇧↑/↓ block reordering via a new BlockMover extension that keeps the caret on the moved block.

Paste now turns VSCode copies with vscode-editor-data into fenced code blocks (with language aliases; markdown/plaintext still parse as markdown) and strips <style>/<script> from pasted HTML so Sheets/Word CSS does not land in the document; ==…== is recognized in markdown paste hints.

The read-only round-trip gate (isRoundTripSafe) is tightened: uppercase HTML entities (&AMP;, etc.) are no longer treated as safe, and unused link reference definitions force read-only so they are not dropped on first save.

Tests cover block moves, highlight parse/serialize, paste paths, mark stacking idempotency, and the new gate cases.

Reviewed by Cursor Bugbot for commit f2b07b1. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR expands the rich markdown editor with safer round-tripping and new editing tools. The main changes are:

  • Adds ==mark== highlight parsing, serialization, toolbar support, and styling.
  • Adds VSCode-aware paste handling for code snippets.
  • Strips pasted style and script HTML before editor parsing.
  • Adds read-only gating for uppercase entities and orphan reference definitions.
  • Adds keyboard shortcuts for moving top-level blocks.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/highlight.ts Adds the custom highlight mark with markdown parsing, rendering, input and paste rules, keyboard support, and a guard for unrepresentable delimiter text.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-paste.ts Adds VSCode clipboard language handling and removes non-content HTML before paste parsing.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/round-trip-safety.ts Adds safer read-only detection for uppercase HTML entities and unused reference definitions.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/block-mover.ts Adds keyboard-driven top-level block reordering while preserving the caret position.

Reviews (5): Last reviewed commit: "feat(rich-markdown-editor): keyboard blo..." | Re-trigger Greptile

@waleedlatif1 waleedlatif1 changed the title feat(rich-markdown-editor): parity pass vs inkeep/open-knowledge (round-trip, paste, highlight, block reorder) feat(rich-markdown-editor): round-trip gate, VSCode/style paste, highlight, block reorder Jul 9, 2026
@waleedlatif1 waleedlatif1 force-pushed the feat/md-editor-parity branch from c8c4580 to deff589 Compare July 9, 2026 19:23
@waleedlatif1 waleedlatif1 force-pushed the feat/md-editor-parity branch from deff589 to 4241b65 Compare July 9, 2026 19:37
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1 waleedlatif1 force-pushed the feat/md-editor-parity branch from 17530cd to eff75c3 Compare July 9, 2026 20:13
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

…ies and orphan ref-defs

Two silent-corruption cases the idempotency probe can't see:

- The HTML-entity safe-list used a case-insensitive regex, so `&AMP;`/`&LT;`/`&GT;` were
  treated as the round-trippable canonical entities and let through as editable, but the
  serializer only round-trips the lowercase forms and mangles the uppercase ones. Make the
  safe-list case-sensitive.
- An unused link/image reference definition (`[x]: url` with no `[x]` reference) is dropped
  entirely on serialize, a deletion the idempotency probe misses. Detect orphan definitions
  and open read-only; used definitions still inline losslessly and stay editable. The use
  check tolerates bracket-internal padding (`[ x ]`), and GFM footnote definitions (`[^id]: …`)
  are excluded since they round-trip verbatim.
…pt> from pasted HTML

- Code copied from VSCode carries a `vscode-editor-data` payload with the source language,
  but its text/html is per-token colored spans that ProseMirror flattens into plain
  paragraphs. Read the payload and paste a real fenced code block with the mapped language.
  markdown/plaintext modes resolve to no language and fall through, so markdown copied from
  VSCode still parses as rich content rather than a fenced block.
- Google Sheets and Word prepend a `<style>` block of CSS that PM's DOM parser walks into
  the document as literal text. Strip <style>/<script> in transformPastedHTML before parsing.
- Add a `==…==` inline-mark hint (allowing a lone interior `=`) so a plain-text paste of
  `==highlight==` routes through the markdown parser and becomes a highlight mark.
Adds a highlight mark rendered as <mark> and serialized to/from ==text== (Pandoc/Obsidian
syntax). A custom inline tokenizer parses ==text== (inner text parsed as inline markdown so
nested marks like ==**bold**== survive; the body allows a lone `=` so ==a=b== round-trips).
`==` cannot be encoded in the delimiter, so an appendTransaction guard strips the mark from
any text that ends up containing `==` (e.g. a toolbar highlight over a==b), keeping the text
and never emitting the corrupting ==a==b==. Comparison operators (x == y) stay literal.
Wired with an input rule, paste rule, Mod-Shift-H, a bubble-menu button, and themed <mark>
styling. Also locks in mark-stacking round-trips across contexts.
Mod-Shift-ArrowUp/ArrowDown swaps the current top-level block with its neighbour, carrying
the caret at its original offset (newBefore + offset, no off-by-one), and no-ops at the
document edges. Exposed as moveBlockUp/moveBlockDown commands (the keyboard shortcuts call
them). Pure UI interaction, no schema change. Covered by tests (order, caret offset, edge
no-op, list stays intact).
@waleedlatif1 waleedlatif1 force-pushed the feat/md-editor-parity branch from eff75c3 to f2b07b1 Compare July 9, 2026 20:21
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit f2b07b1. Configure here.

@waleedlatif1 waleedlatif1 merged commit e802da1 into staging Jul 9, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/md-editor-parity branch July 9, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant